#define _USE_MATH_DEFINES

# include<iostream>
# include<cmath>
# include"EquationSolver.h"

using namespace::std;

/**
* @brief 仿函数类，实现给定函数y1的计算
* 
*/
class Fun1 : public Function
{
public:
    double operator()(double _x)
    {
        return (sin(_x/2) - 1);
    }
};

/**
* @brief 仿函数类，实现给定函数y2的计算
* 
*/
class Fun2 : public Function
{
public:
    double operator()(double _x)
    {
        return (exp(_x) - tan(_x));
    }
};

/**
* @brief 仿函数类，实现给定函数y3的计算
* 
*/
class Fun3 : public Function
{
public:
    double operator()(double x)
    {
        return (x*x*x - 12*x*x + 3*x + 1);
    }
};

/**
* @brief 主函数
* 
*/
int main()
{
    cout << "Solution for Qustion D: " << endl;
    cout << "Test the secant method." << endl;
    double x11, x12, x21, x22, x31, x32, y11, y12, y21, y22, y31, y32;

    // 测试第一个函数，并且改变其初值条件求其他零点
    Fun1 f1;
    Secant Solver11(0, M_PI/2, 0.000001, 0.000001, 10, f1);
    x11 =  Solver11.solve();
    y11 = f1(x11);
    Secant Solver12(4.5*M_PI, 4.7*M_PI, 0.000001, 0.000001, 10, f1);
    x12 =  Solver12.solve();
    y12 = f1(x12);

    // 测试第二个函数，并且改变其初值条件求其他零点
    Fun2 f2;
    Secant Solver21(1, 1.4, 0.000001, 0.000001, 15, f2);
    x21 =  Solver21.solve();
    y21 = f2(x21);
    Secant Solver22(-3.5, -3, 0.000001, 0.000001, 15, f2);
    x22 =  Solver22.solve();
    y22 = f2(x22);

    // 测试第三个函数，并且改变其初值条件求其他零点
    Fun3 f3;
    Secant Solver31(0, -0.5, 0.000001, 0.000001, 10, f3);
    x31 =  Solver31.solve();
    y31 = f3(x31);
    Secant Solver32(0.8, 1, 0.000001, 0.000001, 10, f3);
    x32 =  Solver32.solve();
    y32 = f3(x32);

    cout << "Test for function1: the appropriate root is " << x11 << " , and f1(x11)= " << y11 << endl;
    cout << "Change the initial values: the appropriate root is " << x12 << " , and f1(x12)= " << y12 << endl;
    cout << "Test for function2: the appropriate root is " << x21 << " , and f2(x21)= " << y21 << endl;
    cout << "Change the initial values: the appropriate root is " << x22 << " , and f2(x22)= " << y22 << endl;
    cout << "Test for function3: the appropriate root is " << x31 << " , and f3(x31)= " << y31 << endl;
    cout << "Change the initial values: the appropriate root is " << x32 << " , and f3(x32)= " << y32 << endl;

    cout << "" << endl;
    return 0;
}